iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0

在上一天中,我們了解到React中的元件構成和基礎語法,今天,我們要一同探索的是 ── 更便捷的生成語法!

動態生成


在介紹jQuery的篇章中我們曾提過,我們可以為元件自訂一個模板,而後再傳入資料並生成 ⇒ 【Day12】讓網頁動起來(2)元老級插件jQuery! 。在React中,要做到這些事情又更容易且方便了。

  • jQuery的動態生成:

有著fruit的資料,再由下面的for迴圈一一加進去basket_obj裡面。

const fruit = [
    "apple", "banana", "grapes","durian"
];
const basket_obj = $(".basket");
// 使用迴圈去load資料
for (let i=0;i<fruit.length;i++) {
    basket_obj.append("<li>"+fruit[i]+"</li>")
}

這裡我們先試著改成另一種寫法,下列的寫法較貼近我們在寫React所使用的語法:

const basket_obj = $(".basket");
[
    "apple", "banana", "grapes","durian"
].map((item) => {
    basket_obj.append("<li>"+item+"</li>")	
}))

回到我們的React,我們會這樣寫:

{[資料陣列].map((item) => <compontent/>)}

用相同的範例,我們要先創建裝著元件的容器(basket)、跟水果。

開發流程:

  1. 建置大容器用來裝component
  2. 建置元件
  3. 將元件引入置大容器內
  4. 定義資料並生成(後端、或寫死在程式內)

這邊我選擇在 src/page 的下面創建一個Basket的頁面,並創建 Basket.jsFruit.js
https://ithelp.ithome.com.tw/upload/images/20231008/20160488BQwgyMylgE.png

// Basket.js
const Basket = () => {
    return (
        <></>
    )
}

export default Basket;
// Fruit.js
const Fruit = () => {
    return (
        <></>
    )
}

export default Fruit;

而後我們將basket引入至index.js中:
https://ithelp.ithome.com.tw/upload/images/20231008/20160488hpedcHz4IY.png

  • 撰寫 Basket.js
// Basket.js
import "./Basket.css"

const Basket = () => {
    return (
        <>
            <center>
                <h1>Viscose的水果籃</h1>
                <ul>

                </ul>
            </center>
        </>
    )
}
export default Basket;
/* Basket.css */
h1 {
    font-size: 2em;
    font-weight: bold;
}

除了撰寫 Basket.js 以外,我們還對此標題進行了簡易的優化。

  • 撰寫 Fruit.js

在此處我們設定的是,將fruit的名字傳入,並且把得到的fruit值全數寫進 <li>標籤裡面:

// Fruit.js
const Fruit = ({ fruit_name }) => {
    return (
        <li>{fruit_name}</li>
    )
}

export default Fruit;

接下來要引入我們寫好的 fruit.js ,並寫入map()函式:

{
    ["apple", "banana", "grapes","durian"].map((value,index,array) => {
        console.log(value);
        console.log(index);
        console.log(array);
        console.log("\n");
        return <Fruit fruit_name={value}></Fruit>
    })
}

https://ithelp.ithome.com.tw/upload/images/20231008/20160488OVMbZdFFNX.png

而後網頁呈現便會如下:
https://ithelp.ithome.com.tw/upload/images/20231008/20160488uYOoR1yza9.png
確實是我們預期的結果,我們成功地使用 map() 實現動態生成的效果。
之後我們便可以輕鬆地改變陣列內容,或是從後端取得資料去彈性地生成我們所要的網頁呈現結果。

接下來我們可以看看終端機都跳了哪些內容出來:
在剛才所撰寫的程式中,我們可以發現 map() 的callback函式中可以包含三個傳入值

  • value:數值。
  • index:數值的索引值。
  • array:整個陣列。

我們可以稍微記住這個特性,如果在之後所開發的專案中,需要這個功能時,便可以再拿出來使用:

講完輸出結果,這裡我們也可以發現冒出了一個紅色Warning,它叫我們要對生成的物件賦予一個key值 ──
https://ithelp.ithome.com.tw/upload/images/20231008/20160488h3i9M6fnRE.png

何謂key?


在React中,當您渲染一個動態生成的列表時,每個列表項目都應該擁有一個唯一的"key"屬性。

這是因為React需要使用這個"key"來識別每個列表項目,以便在更新時能夠有效地辨認哪些項目已經被添加、刪除或重新排序。

當您並未提供"key"時,React無法準確地跟蹤列表項目的變化,這可能導致出現錯誤和效能不佳問題。以下是更詳細解釋為什麼要加"key"值的原因:

  1. 有助於React識別項目:"key"值在React內部用於識別每個列表項目。當列表重新渲染時,React使用這些"key"來確定哪些項目需要更新,哪些需要刪除,哪些需要添加。
  2. 提高效能:加上"key"能夠幫助React進行更有效的DOM操作。如果沒有"key",React可能需要重新渲染整個列表,而不僅僅是更新變化的部分。這會導致性能下降。
  3. 維護組件狀態:在某些情況下,組件可能會有自己的狀態,而"key"可以幫助React保持組件的狀態穩定,以防止不必要的重新渲染。

總而言之,為列表中的每個項目提供唯一的"key"屬性是React中的一個重要習慣,它有助於確保正確的渲染和性能優化。當您創建動態列表時,請記得為每個項目添加一個唯一的"key"值。

所以這裡我們便需要引入一個模組:uuid ⇒ https://www.npmjs.com/package/uuid

這個模組可以協助我們快速生成唯一的key值。
https://ithelp.ithome.com.tw/upload/images/20231008/20160488NTPnpO9hO7.png

只需在終端機打入這串指令,便可以安裝uuid的包。

npm install uuid
  • 使用uuid:

將其引入至index.js內。
https://ithelp.ithome.com.tw/upload/images/20231008/20160488Rf7qTuqoOZ.png

而後便可以發現終端機沒有再報錯訊息了,並且我們還可以在React的網頁dev工具中找到它的存在:
https://ithelp.ithome.com.tw/upload/images/20231008/20160488MYwtUSIqLH.png

實作範例:可滑動區域元件化


將動態生成大致摸索並且處理了React的細節後,我們將現學現賣,進入到實作環節 ── 今天的主題是,切版!

BTW,這裡記得要把頁面切換回來,不然後面您會發現不論您怎麼寫都完全沒有結果”
https://ithelp.ithome.com.tw/upload/images/20231008/20160488GcOn92qphZ.png

這裡會參考我們前幾天做的元件 ⇒ 【Day17】常見切版應用(1)可滑動的文章頁面

步驟相同,首先要初始化CSS,我們同樣選用Jack Sharkey 所撰寫的CSS初始化包來作引入:

<link rel="stylesheet" href="init.min.css">

https://ithelp.ithome.com.tw/upload/images/20231002/20160488ATpzAf9Z9U.png

init.css 檔案放在與 index.html 同層的資料夾並將其引入至index.html
https://ithelp.ithome.com.tw/upload/images/20231008/201604884QQ474rlV9.png

我們可以把HTML的東西照貼過來,但是必須留下存放文章區塊的地方。

// ScrollablePanel.js
const ScrollablePanel = () => {
    return (
        <section className="scrollable-panel">
            <div className="scrollable-panel-title">
                <h1>最新消息</h1>
                <h1>
                    NEWS
                </h1>
            </div>
            <div className="scrollable-panel-content">
                <div className="panel-list">
                    
                </div>
            </div>
        </section>
    )
}

export default ScrollablePanel;

這裡一樣使用假圖生成器做demo ⇒ https://fakeimg.pl/

值得注意的是,<img src={"https://fakeimg.pl/350x200/?text="+text} alt=""></img>
這裡我額外設定了一個text當作傳入值,讓這個值給到假圖生成器裡面,使他可以跑不同的文字出來。

// Panel.js
const Panel = ({text}) => {
    return (
        <div className="scrollable-block">
            <div className="block-img">
                <img src={"https://fakeimg.pl/350x200/?text="+text} alt=""></img>
            </div>
            <div className="block-tag">
                熱門的標籤
            </div>
            <div className="block-content">
                <h3>活動的標題yayaya!!!!</h3>
                <div className="block-price">NT$ 100起</div>
            </div>
        </div>
    )
}

export default Panel;

並把CSS的東西貼過來。
https://ithelp.ithome.com.tw/upload/images/20231008/20160488MpARYaNi6P.png

並引入至元件裡面:
https://ithelp.ithome.com.tw/upload/images/20231008/20160488QjnMiAIChF.png

現在元件內容都準備好了,我們便可以將它們串在一起了:
https://ithelp.ithome.com.tw/upload/images/20231008/20160488Nk9azzSl0c.png

  • 使用Panel物件

當然,可以選擇這樣去呼叫並使用Panel元件,但是這樣就太low了!
https://ithelp.ithome.com.tw/upload/images/20231008/20160488VWPNisD61W.png
https://ithelp.ithome.com.tw/upload/images/20231008/201604882OMjFNwZWS.png

使用 map() 函式生成component:

一樣要記得生成uuid並寫入到key值裡面,不然會有報錯訊息喔!

{
    ["HAHA","IRONMAN","IT","REX","哈哈","西西","123"].map(item => {
        return <Panel key={v4()} text={item}></Panel>
    })
}

https://ithelp.ithome.com.tw/upload/images/20231008/2016048844lgyGnfmX.png
https://ithelp.ithome.com.tw/upload/images/20231008/20160488tDULZ9zZUZ.png

再更進階的,我們可以將串列內容都變成一個一個的物件,並擴增至Panel的介面:

{[
    {
        text:"haha",
        price:"87",
        tag:"haha"
    },
    {
        text:"title",
        price:"187",
        tag:"haha"
    },
    {
        text:"iron man",
        price:"987",
        tag:"haha"
    },
    {
        text:"hello world",
        price:"123456",
        tag:"haha"
    }
].map((item) => (
    return <Panel 
				key={v4()}
        text={item["text"]} 
        price={item["price"]} 
        tag={item["tag"]}></Panel>
))}

https://ithelp.ithome.com.tw/upload/images/20231008/20160488tEfHHBH6In.png
https://ithelp.ithome.com.tw/upload/images/20231008/20160488WwxBbq7nOI.png

以上,便完成啦!


github source code
今天的教學便到此結束了,是不是沒想到先前所學的切版也可以用React來實現呢?

動態生成可活用的地方可多了呢,也不難發現大多數元件玩的都是這套公式,多寫幾次便會記起來了,甚至可以往後延伸做各式各樣酷酷又複雜的元件呢!

明天我們會講解React中很重要的一環 ── hook,也會提到useEffect & useState,敬請期待,我們明天見!


上一篇
【Day22】淺談 React.js(1)React基本構成 & 語法
下一篇
【Day24】淺談 React.js(3)React useState & useEffect
系列文
連我阿公都會-手把手教你架網站 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言